package com.yangcangclub.trade.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.rocketmq.common.message.Message;
import com.google.common.collect.Maps;
import com.yangcangclub.commons.exception.ApolloException;
import com.yangcangclub.commons.result.MessageEnum;
import com.yangcangclub.commons.utils.StringUtil;
import com.yangcangclub.merchandise.bean.Product;
import com.yangcangclub.trade.base.TradeBaseService;
import com.yangcangclub.trade.bean.*;
import com.yangcangclub.trade.service.TradeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by user on 2017/2/24.
 */
@Service
public class TradeServiceImpl extends TradeBaseService implements TradeService {

    private static Logger logger = LoggerFactory.getLogger(TradeServiceImpl.class);

    /**创建订单
     * 目前不涉及到物流选择和地址管理，expressId,addressId 可为空
     * */
    @Override
    @Transactional(rollbackFor= ApolloException.class)
    public Map<String, Object> buy(String totalPrice, int userId, JSONObject productListJson, String payType, String source,
                                   String province, String city, String county, String contactName, String contactMobile, String contactAddress,
                                   int expressId, String userRemark,int addressId) throws Exception {
        Map<String,Object> map = Maps.newHashMap();
        //检查支付类型，不为空，且为数字
//        if(StringUtil.isEmpty(payType) || !StringUtil.isNumber(payType)){
//            throw new ApolloException(MessageEnum.PAY_TYPE_FAILURE);
//        }
//        if(Integer.valueOf(payType)!=0 && Integer.valueOf(payType)!=1 && Integer.valueOf(payType)!=3){
//            throw new ApolloException(MessageEnum.PAY_TYPE_FAILURE);
//        }
//        //支付类型如果为微信公众号支付1，则openid不能为空
//        if(Integer.valueOf(payType) == 1){
//            if(StringUtil.isEmpty(openid)){throw new ApolloException(MessageEnum.MISSING_PAYMENT_PARAMETERS);}
//        }
        //检查商品参数是否为空
        if(StringUtil.isEmpty(productListJson.getString("productList"))){
            throw new ApolloException(MessageEnum.PRODUCT_NOT_EXIST);
        }
        //价格初始化
        BigDecimal tradeTotalPrice = new BigDecimal(0);//订单总价=商品总价格+运费-折扣价格[目前没有折扣]
        BigDecimal productTotalPrice = new BigDecimal(0);//商品总价格
        BigDecimal freightPrice = new BigDecimal(0);//运费 运费目前写成固定

        List productList = productListJson.getJSONArray("productList");
        List<TradeDetails> productTempsList = new ArrayList<>();
        String body = "";
        List<Integer> trolleyIdList = new ArrayList<>();
        for(int i=0;i<productList.size();i++){
            JSONObject productJson = JSONObject.parseObject(productList.get(i).toString());
            if(StringUtil.isNotNumber(productJson.getString("productId"))
                    || StringUtil.isNotNumber(productJson.getString("quantity"))){
                throw new ApolloException(MessageEnum.PRODUCT_NOT_EXIST);
            }
            //数量
            int quantity = productJson.getInteger("quantity");
            if(quantity >99){throw new ApolloException(MessageEnum.PRODUCT_QUANTITY_TOO_MANY);}
            if(quantity <1){throw new ApolloException(MessageEnum.PRODUCT_QUANTITY_TOO_LITTLE);}
            //获取商品信息
            Product product = productBaseDomain.getProductById(productJson.getInteger("productId"));
            //检查商品是否存在
                if(product == null){
                throw new ApolloException(MessageEnum.PRODUCT_NOT_EXIST);
            }
            //检查商品是否上架
            if(product.getStatus() != 1){
                throw new ApolloException(MessageEnum.PRODUCT_SOLD_OUT);
            }

            //判断下是否会员
            Map<String,Object> userMap = userComponent.getUserInfo(userId);
            Map<String,Object> user = (Map<String,Object>)userMap.get("userInfo");
            //非普通商品要验证是否为会员，会员才能购买各大仓
            if(product.getWarehouseType() != 1){
                if(!user.get("user_mark").equals("4")){throw new ApolloException(MessageEnum.ERROR_MEMBER_EXCLUSIVE_2);}
            }
            //检查商品是否限购，
            //如果限购判断数量是否为1
            if(product.getIsLimit() == 2){
                if(!user.get("user_mark").equals("4")){throw new ApolloException(MessageEnum.ERROR_MEMBER_EXCLUSIVE);}

                if(quantity != 1){throw new ApolloException(MessageEnum.PRODUCT_QUANTITY_RESTRICTION);}
                //检查用户是否曾经下过单
                Map queryMap = Maps.newHashMap();
                queryMap.put("userId",userId);
                queryMap.put("productId",product.getId());
                //不包括的状态
//                List<String> statusNotInList = new ArrayList<String>();
//                statusNotInList.add("C");
//                statusNotInList.add("F");
//                queryMap.put("statusNotInList",statusNotInList);
                List<TradeDetails> list = tradeDetailsDomain.selectPageBreakByCondition(queryMap,1,1);
                if(list.size()>0){
                    throw new ApolloException(MessageEnum.REPEAT_ACTIVITIES_FAILURE);
                }
                //限购商品是否在购买时间内购买
                if(product.getStartTime().getTime()>System.currentTimeMillis()){
                    throw new ApolloException(MessageEnum.ERROR_ACTIVITY_NOT_STARTED);
                }
                if(product.getEndTime().getTime()<System.currentTimeMillis()){
                    throw new ApolloException(MessageEnum.ERROR_ACTIVITY_IS_OVEER);
                }
            }
            //如果不是限购商品要走清除购物车流程（限购商品不走购物车，清除时不必清理）
            if(product.getIsLimit() != 2){
                if(StringUtil.isNotNumber(productJson.getString("trolleyId"))){
                    throw new ApolloException(MessageEnum.PRODUCT_NOT_EXIST);
                }
                //将购物车id添加到list里面，创建订单成功后清除对应的购物车记录
                trolleyIdList.add(productJson.getInteger("trolleyId"));
            }
            //检查商品是否有货
            if(product.getInventory()<quantity){
                throw new ApolloException(MessageEnum.INSUFFICIENT_GOODS);
            }
            //临时保存订单详细对象
            TradeDetails tradeDetails = new TradeDetails();
            tradeDetails.setProductId(product.getId());
            tradeDetails.setProductName(product.getName());
            tradeDetails.setProductUrl(product.getBannerUrl());
            tradeDetails.setQuality(quantity);
            tradeDetails.setUnitPrice(product.getUnitPrice()
                    .setScale(2,BigDecimal.ROUND_DOWN));
//            tradeDetails.setActivityId();
//            tradeDetails.setActivityType();
            tradeDetails.setProductTotalPrice(product.getUnitPrice().
                    multiply(new BigDecimal(quantity))
                    .setScale(2,BigDecimal.ROUND_DOWN));
            tradeDetails.setUserId(userId);
            tradeDetails.setStatus("S");
            tradeDetails.setCreateDate(new Date());
            tradeDetails.setIsFuxi(product.getIsFuxi());
            tradeDetails.setIsLimit(product.getIsLimit());
            tradeDetails.setFreightPrice(product.getShipping());
            productTempsList.add(tradeDetails);
            //计算所有商品总价格
            productTotalPrice=productTotalPrice.add(tradeDetails.getProductTotalPrice());
            if(StringUtil.isEmpty(body)){
                body+=product.getName().trim();
                if(productList.size()>1)body+="等";;
            }
        }
        //判断订单总价
        tradeTotalPrice = productTotalPrice.add(freightPrice).setScale(2,BigDecimal.ROUND_DOWN);
        if(tradeTotalPrice.compareTo(new BigDecimal(totalPrice)) != 0){
            throw new ApolloException(MessageEnum.TOPIC_PRAICE_HAS_CHANGED);
        }
        //生成订单号
        String tradeNo = String.valueOf(identities.getTradeNo(userId));
        //创建订单
        TradeSummary tradeSummary = new TradeSummary();
        tradeSummary.setTradeNo(tradeNo);
//        tradeSummary.setPayType(Integer.valueOf(payType));
        tradeSummary.setPayStatus("U");
        tradeSummary.setSource(source);
        tradeSummary.setTradeTotalPrice(tradeTotalPrice);
        tradeSummary.setProductTotalPrice(productTotalPrice);
        tradeSummary.setFreightPrice(freightPrice);
        tradeSummary.setShouldPrice(tradeTotalPrice);
        tradeSummary.setRealPrice(new BigDecimal(0).setScale(2,BigDecimal.ROUND_DOWN));
        tradeSummary.setProvince(province);
        tradeSummary.setCity(city);
        tradeSummary.setCounty(county);
        tradeSummary.setContactName(contactName);
        tradeSummary.setContactMobile(contactMobile);
        tradeSummary.setContactAddress(contactAddress);
//        tradeSummary.setExpressName();
//        tradeSummary.setExpressId();
        tradeSummary.setUserId(userId);
        //查询活动
//        tradeSummary.setActivityId();
        tradeSummary.setStatus("S");
        tradeSummary.setUserRemark(userRemark);
        tradeSummary.setCreateDate(new Date());

        int tradeId = tradeDomain.insertTrade(tradeSummary);
        //创建订单详细
        for(TradeDetails tradeDetails:productTempsList){
            tradeDetails.setTradeNo(tradeNo);
            tradeDetailsDomain.insertTradeDetails(tradeDetails);
        }
        //创建地址（冗余用）
        TradeAddress tradeAddress = new TradeAddress();
        tradeAddress.setTradeNo(tradeNo);
        tradeAddress.setProvince(province);
        tradeAddress.setCity(city);
        tradeAddress.setCounty(county);
        tradeAddress.setContactName(contactName);
        tradeAddress.setContactMobile(contactMobile);
        tradeAddress.setContactAddress(contactAddress);
        tradeAddress.setUserId(userId);
        tradeAddress.setCreateDate(new Date());
        tradeAddressDomain.insertTradeAddress(tradeAddress);
        //减库存
        for(TradeDetails tradeDetails:productTempsList){
            boolean b = productBaseDomain.sellReduceInventoriesById(tradeDetails.getProductId(),tradeDetails.getQuality());
            if(!b){//减库存失败
                throw new ApolloException(MessageEnum.COMMODITY_REDUCE_FAILURE);
            }
        }
//        //发起支付内容
//        String title = "羊仓"+tradeNo;
//        String reqNo = identities.uuid2();
//        //支付宝支付
//        if(String.valueOf(PayTypeEnum.AliPay.getValue()).equals(payType)){
//            String url = alipayUtil.getAlipayParameter(tradeNo,tradeSummary.getShouldPrice().toString(),title,body,reqNo);
//            map.put("tradePayParam",url);
//        }
//        //支付宝支付
//        if(String.valueOf(PayTypeEnum.AliPayWeb.getValue()).equals(payType)){
//            String url = alipayUtil.getAlipayWebParameter(tradeNo,tradeSummary.getShouldPrice().toString(),title,body,reqNo);
//            map.put("tradePayParam",url);
//        }
//        //微信公众号支付
//        if(String.valueOf(PayTypeEnum.WeChatPublicPay.getValue()).equals(payType)){
//            map.put("tradePayParam",weChatUtil.getWeChatParameter(tradeNo,tradeSummary.getShouldPrice().toString(),title,body,openid,reqNo));
//        }
//        //生成交易请求
//        TradeReqLogs tradeReqLogs = new TradeReqLogs();
//        tradeReqLogs.setTradeNo(tradeNo);
//        tradeReqLogs.setReqNo(reqNo);
//        if(String.valueOf(PayTypeEnum.WeChatPublicPay.getValue()).equals(payType)){
//            Map<String,String> m = (Map<String, String>) map.get("tradePayParam");
//            tradeReqLogs.setPrepayId(m.get("prepayId").toString());
//        }
//        tradeReqLogs.setReqType(1);
//        tradeReqLogs.setReqPrice(tradeSummary.getShouldPrice());
//        tradeReqLogs.setReqData(map.toString());
//        tradeReqLogs.setUserId(userId);
//        tradeReqLogs.setReqDate(new Date());
//        tradeReqLogs.setResultStatus(2);
//        tradeReqLogsDomain.insertTradeReqLogs(tradeReqLogs);
        //清除购物车对应的商品
        if(trolleyIdList.size()>0){
            trolleyBasisDomain.delProductFromTrolley(userId,trolleyIdList);
        }
        map.put("tradeNo",tradeNo);
        map.put("tradeId",tradeId);
        return map;
    }
    /**更新订单
     * updateType:express（物流）,contact（收件人信息）,other（其他信息 客服备注）
     * id:订单id
     * updateInfo:
     * express-->expressName,expressId,expressNo
     * contact-->province,city,county,contactName,contactMobile,contactAddress
     * other-->serviceRemark
     * updateUserId:操作者id
     * */
    @Override
    @Transactional(rollbackFor= ApolloException.class)
    public boolean updateTrade(String updateType,int id, JSONObject updateInfo,int updateUserId) throws Exception {
        TradeSummary trade = tradeDomain.selectTradeById(id);
        if(trade == null){
            throw new ApolloException(MessageEnum.ERROR_TRADE_NOT_FOUND);
        }
        if(!"express".equals(updateType) && !"contact".equals(updateType) && !"other".equals(updateType)){
            throw new ApolloException(MessageEnum.ERROR_TRADE_UPDATE);
        }
        int updateCount = tradeDomain.updateTrade(updateType,id,trade.getTradeNo(),trade.getUserId(),updateInfo,updateUserId);
        if(updateCount>0){
            return true;
        }
        return false;
    }

    /**更新订单状态
     * id:订单id
     * status:
     * S待付款[创建订单后默认状态]D待发货[由支付成功异步回调实现]R已发货[由updateTrade方法实现]
     * E已完成[由本方法实现]C已取消[由本方法实现]
     * F已退款[由退款方法实现]
     * updateUserId:操作者id
     * */

    @Override
    @Transactional(rollbackFor= ApolloException.class)
    public boolean updateTradeStatus(int userId, int tradeId, String status) throws Exception {
        TradeSummary trade = tradeDomain.selectTradeByIdAndUserId(userId,tradeId);
        if(trade == null){
            throw new ApolloException(MessageEnum.ERROR_TRADE_NOT_FOUND);
        }
        if(!"E".equals(status)&&!"C".equals(status)){
            throw new ApolloException(MessageEnum.ILLEGAL_ORDER_STATUS_CHANGE);
        }
        //变更状态为已完成E
        if("E".equals(status)){
            //判断前置状态是否为已发货R状态
            if(!"R".equals(trade.getStatus())){throw new ApolloException(MessageEnum.ILLEGAL_ORDER_STATUS_CHANGE);}
            if(tradeDomain.updateTradeStatus(tradeId,"E","",trade.getUserId()))
                return true;
        }
        //变更状态为已取消C
        if("C".equals(status)){
            if(tradeDomain.updateTradeStatus(tradeId,"C","",trade.getUserId())){
                boolean b = tradeDetailsDomain.updateTradeDetailsStatusByTrandNo(trade.getTradeNo(),"C");
                if( b==true ){
                    //恢复库存
                    List<TradeDetails> list = tradeDetailsDomain.selectTradeDetailsByTradeNo(trade.getTradeNo());
                    for(TradeDetails tradeDetails:list){
                        if(!productBaseDomain.recoverInventoriesById(tradeDetails.getProductId(),tradeDetails.getQuality()))
                            throw new ApolloException(MessageEnum.INVENTORY_UPDATE_FAILURE);
                    }
                    return true;
                }else{
                    return false;
                }
            }else{
                return false;
            }
        }
        return false;
    }

    /** 后台管理 更新订单状态
     * @param tradeId
     * @param status
     * @param serviceRemark
     * @param updateUserId
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor= ApolloException.class)
    public boolean updateTradeStatus(int tradeId, String status, String serviceRemark,int updateUserId) throws Exception {
        TradeSummary trade = tradeDomain.selectTradeById(tradeId);
        if(trade == null){
            throw new ApolloException(MessageEnum.ERROR_TRADE_NOT_FOUND);
        }
        if(!"E".equals(status)&&!"C".equals(status)){
            throw new ApolloException(MessageEnum.ILLEGAL_ORDER_STATUS_CHANGE);
        }
        //变更状态为已完成E
        if("E".equals(status)){
            //判断前置状态是否为已发货R状态
            if(!"R".equals(trade.getStatus())){throw new ApolloException(MessageEnum.ILLEGAL_ORDER_STATUS_CHANGE);}
            if(tradeDomain.updateTradeStatus(tradeId,"E",serviceRemark,updateUserId))
                return true;
        }
        //变更状态为已取消C
        if("C".equals(status)){
            if(tradeDomain.updateTradeStatus(tradeId,"C",serviceRemark,updateUserId)){
                boolean b = tradeDetailsDomain.updateTradeDetailsStatusByTrandNo(trade.getTradeNo(),"C");
                if( b ){
                    //恢复库存
                    List<TradeDetails> list = tradeDetailsDomain.selectTradeDetailsByTradeNo(trade.getTradeNo());
                    for(TradeDetails tradeDetails:list){
                        if(!productBaseDomain.recoverInventoriesById(tradeDetails.getProductId(),tradeDetails.getQuality()))
                            throw new ApolloException(MessageEnum.INVENTORY_UPDATE_FAILURE);
                    }
                    return true;
                }else{
                    return false;
                }
            }else{
                return false;
            }
        }
        return false;
    }

    /**获取订单详细列表（API使用）
     * @param pageNum
     * @param pageSize
     * @param orderBy
     * @param map
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, Object> getTradeList(int pageNum, int pageSize, String orderBy, Map map) throws Exception {

        map.put("sortColumns",StringUtil.isNotEmpty(orderBy)?orderBy:"");
        List<TradeVo> list = tradeDomain.selectTradeVoPageBreakByCondition(map,pageNum,pageSize);
        int total = tradeDomain.getManagerTradeListNum(map);
        Map m = Maps.newHashMap();
        m.put("rows",list);
        m.put("total",total);
        return m;
    }

    /**获取订单详细列表（后台管理使用）
     * @param start
     * @param pageSize
     * @param map
     * @return
     */
    @Override
    public Map<String, Object> getManagerTradeList(int start, int pageSize, Map map) {
        List<TradeVo> tradeVoList = tradeDomain.getManagerTradeList(start,pageSize,map);
        int total = tradeDomain.getManagerTradeListNum(map);
        map.put("rows",tradeVoList);
        map.put("total",total);
        return map;
    }

    /**获取订单明细，API使用
     * @param userId
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    public TradeVo getTradeDetailsById(int userId, int id) throws Exception {
        return tradeDomain.selectTradeVoByIdAndUserId(userId,id);
    }

    /**获取订单明细，后台使用
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    public TradeVo getTradeDetailsById(int id) throws Exception {
        return tradeDomain.selectTradeAllInfoById(id);
    }

    /**支付宝支付 异步通知
     * @param map
     * @return
     * @throws UnsupportedEncodingException
     */
    @Override
    @Transactional(rollbackFor= ApolloException.class)
    public boolean tradeAlipayNotify(Map<String, String> map) throws UnsupportedEncodingException{
        logger.info("支付宝异步通知 接收参数:"+map.toString());
        if(StringUtil.isEmpty(map.get("trade_status"))){
            logger.info("支付宝异步通知状态码异常，交易目前所处的状态trade_status为空"
            +"[notify_id:"+map.get("notify_id")+"tradeNo:"+map.get("out_trade_no")+"]");
            return false;
        }
        if(!alipayUtil.verify(map)){
            logger.info("支付宝异步通知参数验证失败"
                    +"[notify_id:"+map.get("notify_id")+"tradeNo:"+map.get("out_trade_no")+"]");
            return false;
        }
        logger.info("支付宝异步通知参数验证成功"
                +"[notify_id:"+map.get("notify_id")+"tradeNo:"+map.get("out_trade_no")+"]");
        if(map.get("trade_status").equalsIgnoreCase("TRADE_SUCCESS")){
            //获取交易日志对应的交易类型
            Map reqMap = Maps.newHashMap();
            reqMap.put("tradeNo",map.get("out_trade_no"));
            reqMap.put("reqNo",map.get("passback_params"));
            List<TradeReqLogs> reqLogsList = tradeReqLogsDomain.selectTradeReqLogsByCondition(reqMap);
            if(reqLogsList == null || reqLogsList.size()==0){
                logger.info("支付宝异步通知未获取到请求日志"
                        +"[notify_id:"+map.get("notify_id")+"tradeNo:"+map.get("out_trade_no")+"reqNo:"+map.get("passback_params")+"]");
                return false;
            }
            TradeReqLogs tradeReqLogs = reqLogsList.get(0);
            reqMap.put("resultType",tradeReqLogs.getReqType());
            List<TradeResultLogs> resultLogsList = tradeResultLogsDomain.selectTradeResultLogsByCondition(reqMap);
            if(resultLogsList.size() > 0){
                logger.info("支付宝异步通知已经成功接收过"
                        +"[notify_id:"+map.get("notify_id")+"tradeNo:"+map.get("out_trade_no")+"reqNo:"+map.get("passback_params")+"]");
                return true;
            }
            //保存异步通知返回结果
            TradeResultLogs tradeResultLogs = new TradeResultLogs();
            tradeResultLogs.setTradeNo(map.get("out_trade_no"));
            tradeResultLogs.setReqNo(map.get("passback_params"));
            tradeResultLogs.setResultData(alipayUtil.createLinkString(map));
            tradeResultLogs.setResultDate(new Date());
            tradeResultLogs.setResultType(tradeReqLogs.getReqType());
            tradeResultLogs.setReturnTradeNo(map.get("trade_no"));
            int tradeResultLogsId = tradeResultLogsDomain.insertTradeResultLogs(tradeResultLogs);
            if(tradeResultLogsId > 0){
                //更新请求日志结果
                tradeReqLogsDomain.updateTradeReqLogsById(tradeReqLogs.getId(),0);
                //更新订单
                TradeSummary trade = tradeDomain.selectTradeByTradeNo(map.get("out_trade_no"));
                tradeDomain.updateTradePayStatus(trade.getId(),map.get("out_trade_no"),
                map.get("trade_no"), map.get("buyer_logon_id"),
                "P", new BigDecimal(map.get("buyer_pay_amount")),
                        "D", "",0);
                return true;
            }
        }else{
            logger.info("支付宝异步通知交易状态异常"
                +"[trade_status:"+map.get("trade_status")+"trade_no:"+map.get("trade_no")+"tradeNo:"+map.get("out_trade_no")+"reqNo:"+map.get("passback_params")+"]");
            return false;
        }
        return false;
    }

    /**微信支付 异步通知
     * @param map
     * @return
     * @throws UnsupportedEncodingException
     */
    @Override
    @Transactional(rollbackFor= ApolloException.class)
    public boolean tradeWechatNotify(Map<String, String> map) throws UnsupportedEncodingException{
        logger.info("微信支付异步通知 接收参数:"+map.toString());
        if ("SUCCESS".equalsIgnoreCase(map.get("result_code")) && "SUCCESS".equals(map.get("return_code"))) {
            //获取交易日志对应的交易类型
            Map reqMap = Maps.newHashMap();
            reqMap.put("tradeNo",map.get("out_trade_no"));
            reqMap.put("reqNo",map.get("attach"));
            List<TradeReqLogs> reqLogsList = tradeReqLogsDomain.selectTradeReqLogsByCondition(reqMap);
            if(reqLogsList == null || reqLogsList.size()==0){
                logger.info("微信异步通知未获取到请求日志"
                        +"[transaction_id:"+map.get("transaction_id")+"tradeNo:"+map.get("out_trade_no")+"reqNo:"+map.get("attach")+"]");
                return false;
            }
            TradeReqLogs tradeReqLogs = reqLogsList.get(0);
            reqMap.put("resultType",tradeReqLogs.getReqType());
            List<TradeResultLogs> resultLogsList = tradeResultLogsDomain.selectTradeResultLogsByCondition(reqMap);
            if(resultLogsList.size() > 0){
                logger.info("微信异步通知已经成功接收过"
                        +"[transaction_id:"+map.get("transaction_id")+"tradeNo:"+map.get("out_trade_no")+"reqNo:"+map.get("attach")+"]");
                return true;
            }
            //保存异步通知返回结果
            TradeResultLogs tradeResultLogs = new TradeResultLogs();
            tradeResultLogs.setTradeNo(map.get("out_trade_no"));
            tradeResultLogs.setReqNo(map.get("attach"));
            tradeResultLogs.setResultData(alipayUtil.createLinkEncodedURL(map));
            tradeResultLogs.setResultDate(new Date());
            tradeResultLogs.setResultType(tradeReqLogs.getReqType());
            tradeResultLogs.setReturnTradeNo(map.get("transaction_id"));
            int tradeResultLogsId = tradeResultLogsDomain.insertTradeResultLogs(tradeResultLogs);
            if(tradeResultLogsId > 0){
                //更新请求日志结果
                tradeReqLogsDomain.updateTradeReqLogsById(tradeReqLogs.getId(),0);
                //更新订单
                TradeSummary trade = tradeDomain.selectTradeByTradeNo(map.get("out_trade_no"));
                tradeDomain.updateTradePayStatus(trade.getId(),map.get("out_trade_no"),
                        map.get("transaction_id"), map.get("openid"),
                        "P", new BigDecimal(map.get("total_fee")).divide(new BigDecimal(100)),
                        "D", "",0);
                return true;
            }
        }else{
            logger.info("微信异步通知交易状态异常"
                    +"[result_code:"+map.get("result_code")+"return_code:"+map.get("return_code")+"return_msg:"+map.get("return_msg")+"]");
            return false;
        }
            return false;
    }

    /**继续支付、获取支付参数
     * @param userId
     * @param tradeId
     * @param payType
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(rollbackFor= ApolloException.class)
    public Map<String, Object> continuePay(int userId, int tradeId, String payType) throws Exception {
        Map<String,Object> map = Maps.newHashMap();
        TradeSummary tradeSummary = tradeDomain.selectTradeByIdAndUserId(userId,tradeId);
        //检查支付类型，不为空，且为数字
        if(StringUtil.isEmpty(payType) || !StringUtil.isNumber(payType)){
            throw new ApolloException(MessageEnum.PAY_TYPE_FAILURE);
        }
        //支付类型如果为微信公众号支付1，则openid不能为空
        String openid = "";
        if(Integer.valueOf(payType) == 1){
            Map<String,Object> userMap =  userComponent.getWxOpenIdByUserId(userId);
            openid = userMap.containsKey("openId")?userMap.get("openId").toString():"";
            if(StringUtil.isEmpty(openid)){throw new ApolloException(MessageEnum.MISSING_PAYMENT_PARAMETERS);}
        }
        if(!"S".equals(tradeSummary.getStatus()) || !"U".equals(tradeSummary.getPayStatus())){
            throw new ApolloException(MessageEnum.PAY_DELAY_TIMEOUT);
        }

        String title = "羊仓"+tradeSummary.getTradeNo();

        String body = "";
        List<TradeDetails> list = tradeDetailsDomain.selectTradeDetailsByTradeNo(tradeSummary.getTradeNo());
        for(TradeDetails tradeDetails:list){
            if(StringUtil.isEmpty(body)){
                body+="羊仓-";
                body+=tradeDetails.getProductName();
                if(list.size()>1)body+="等";
            }
        }
        //获取生成交易请求数据
        Map reqMap = Maps.newHashMap();
        reqMap.put("tradeNo",tradeSummary.getTradeNo());
        reqMap.put("reqType",1);
        List<TradeReqLogs> tradeReqLogsList = tradeReqLogsDomain.selectTradeReqLogsByCondition(reqMap);
        //这种情况几乎不可能出现，因为创建订单后必须要声称一条交易请求记录
        if(tradeReqLogsList.size()==0){
            String reqNo = identities.uuid2();
            //支付宝支付
            if(String.valueOf(PayTypeEnum.AliPay.getValue()).equals(payType)){
                String url = alipayUtil.getAlipayParameter(tradeSummary.getTradeNo(),tradeSummary.getShouldPrice().toString(),title,body,reqNo);
                map.put("tradePayParam",url);
            }
            //微信公众号支付
            if(String.valueOf(PayTypeEnum.WeChatPublicPay.getValue()).equals(payType)){
                map.put("tradePayParam",weChatUtil.getWeChatParameter(tradeSummary.getTradeNo(),tradeSummary.getShouldPrice().toString(),title,body,openid,reqNo));
            }
            //支付宝支付
            if(String.valueOf(PayTypeEnum.AliPayWeb.getValue()).equals(payType)){
                String url = alipayUtil.getAlipayWebParameter(tradeSummary.getTradeNo(),tradeSummary.getShouldPrice().toString(),title,body,reqNo);
                map.put("tradePayParam",url);
            }
            //生成交易请求
            TradeReqLogs tradeReqLogs = new TradeReqLogs();
            tradeReqLogs.setTradeNo(tradeSummary.getTradeNo());
            tradeReqLogs.setReqNo(reqNo);
            if(String.valueOf(PayTypeEnum.WeChatPublicPay.getValue()).equals(payType)){
                Map<String,String> m = (Map<String, String>) map.get("tradePayParam");
                tradeReqLogs.setPrepayId(m.get("prepayId").toString());
            }
            tradeReqLogs.setReqType(1);
            tradeReqLogs.setReqPrice(tradeSummary.getShouldPrice());
            tradeReqLogs.setReqData(map.toString());
            tradeReqLogs.setUserId(userId);
            tradeReqLogs.setReqDate(new Date());
            tradeReqLogs.setResultStatus(2);
            tradeReqLogsDomain.insertTradeReqLogs(tradeReqLogs);
            map.put("tradeNo",tradeSummary.getTradeNo());
            map.put("tradeId",tradeId);
            //更新支付类型
            tradeDomain.updateTradePayType(tradeSummary.getId(),Integer.valueOf(payType));
            return map;
        }

        TradeReqLogs tradeReqLogs = tradeReqLogsList.get(0);
        if(tradeReqLogs.getResultStatus()==0){
            throw new ApolloException(MessageEnum.REPEAT_OPERATION);
        }
        //支付宝支付
        if(String.valueOf(PayTypeEnum.AliPay.getValue()).equals(payType)){
            String url = alipayUtil.getAlipayParameter(tradeSummary.getTradeNo(),tradeSummary.getShouldPrice().toString(),title,body,tradeReqLogs.getReqNo());
            map.put("tradePayParam",url);
        }
        //支付宝支付
        if(String.valueOf(PayTypeEnum.AliPayWeb.getValue()).equals(payType)){
            String url = alipayUtil.getAlipayWebParameter(tradeSummary.getTradeNo(),tradeSummary.getShouldPrice().toString(),title,body,tradeReqLogs.getReqNo());
            map.put("tradePayParam",url);
        }
        //微信公众号支付
        if(String.valueOf(PayTypeEnum.WeChatPublicPay.getValue()).equals(payType)){
            map.put("tradePayParam",weChatUtil.getWeChatParameter(tradeSummary.getTradeNo(),tradeReqLogs.getPrepayId()));
        }
        map.put("tradeNo",tradeSummary.getTradeNo());
        map.put("tradeId",tradeSummary.getId());

        //更新支付类型
        tradeDomain.updateTradePayType(tradeSummary.getId(),Integer.valueOf(payType));
        return map;
    }

    /**获取超时订单-30分钟未支付
     * @return
     */
    @Override
    public List<TradeSummary> selectPayTimeOutTrades(int time) {
        return tradeDomain.selectPayTimeOutTrades(time);
    }

    /**取消超时订单（变更订单状态、变更订单详细状态、恢复商品库存）
     * @param tradeId
     * @param tradeNo
     * @return
     */
    @Override
    @Transactional(rollbackFor= ApolloException.class)
    public boolean cancelPayTimeOutTrades(int tradeId,String tradeNo) {
        if(tradeDomain.updateTradeStatus(tradeId,"C","systemCancelPayTimeOut",0)){
            boolean b = tradeDetailsDomain.updateTradeDetailsStatusByTrandNo(tradeNo,"C");
            if( b ){
                //恢复库存
                List<TradeDetails> list = tradeDetailsDomain.selectTradeDetailsByTradeNo(tradeNo);
                for(TradeDetails tradeDetails:list){
                    if(!productBaseDomain.recoverInventoriesById(tradeDetails.getProductId(),tradeDetails.getQuality()))
                    throw new ApolloException(MessageEnum.INVENTORY_UPDATE_FAILURE);
                }
                return true;
            }else{
                return false;
            }
        }else{
            return false;
        }
    }

    @Override
    public TradeVo getTradeDetailsByTradeNo(String tradeNo) throws Exception {
        return tradeDomain.selectTradeAllInfoByTradeNo(tradeNo);
    }

}
